package com.huiminpay.merchant.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.PhoneUtil;
import com.huiminpay.common.cache.util.StringUtil;
import com.huiminpay.merchant.api.MerchantService;
import com.huiminpay.merchant.convert.MerchantCovert;
import com.huiminpay.merchant.convert.StaffConvert;
import com.huiminpay.merchant.convert.StoreConvert;
import com.huiminpay.merchant.dto.MerchantDTO;
import com.huiminpay.merchant.dto.StaffDTO;
import com.huiminpay.merchant.dto.StoreDTO;
import com.huiminpay.merchant.entity.Merchant;
import com.huiminpay.merchant.entity.Staff;
import com.huiminpay.merchant.entity.Store;
import com.huiminpay.merchant.entity.StoreStaff;
import com.huiminpay.merchant.mapper.MerchantMapper;
import com.huiminpay.merchant.mapper.StaffMapper;
import com.huiminpay.merchant.mapper.StoreMapper;
import com.huiminpay.merchant.mapper.StoreStaffMapper;
import com.huiminpay.user.api.TenantService;
import com.huiminpay.user.dto.tenant.CreateTenantRequestDTO;
import com.huiminpay.user.dto.tenant.TenantDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author suozhenhua
 * @since 2021-03-15
 */
@Slf4j
@Service
public class MerchantServiceImpl implements MerchantService {
    @Autowired
    MerchantMapper merchantMapper;
    @Autowired
    StoreMapper storeMapper;

    @Autowired
    StaffMapper staffMapper;

    @Autowired
    StoreStaffMapper storeStaffMapper;
    @Reference //租户服务
    TenantService tenantService;

    /**
     * 根据ID查询商户信息
     *
     * @param
     * @return
     */
    @Override
    public MerchantDTO queryMerchantById(Long id) {
        Merchant merchant = merchantMapper.selectById(id);
        //entity 转换为 DTO
        MerchantDTO merchantDTO = MerchantCovert.INSTANCE.entity2dto(merchant);
        /*MerchantDTO merchantDTO = new MerchantDTO();

        merchantDTO.setId(merchant.getId());
        merchantDTO.setMerchantName(merchant.getMerchantName());
        merchantDTO.setMerchantNo(merchant.getMerchantNo());
        merchantDTO.setMerchantAddress(merchant.getMerchantAddress());*/
        return merchantDTO;
    }

    /**
     * 商户注册
     * 流程分析：1、校验数据的合法性
     *          2、新增租户和账户
     *          2、创建商户
     *          3、商户下新增门店
     *          4、新增员工-默认的管理员
     *          5、设置管理员-绑定关系
     * @param merchantDTO 商户信息
     * @return 新增之后的商户信息
     */
    @Override
    public MerchantDTO createMerchant(MerchantDTO merchantDTO) {
        //1、效验

        //参数校验
        if (merchantDTO == null) {
            throw new BusinessException(CommonErrorCode.E_100108);
        }
        //手机号非空
        if (StringUtil.isBlank(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        //手机号 唯一性校验:先查寻数据库 如果存在 则抛出异常
        Integer integer = merchantMapper.selectCount(
                new LambdaQueryWrapper<Merchant>().eq(Merchant::getMobile, merchantDTO.getMobile()));
        if (integer > 0) {
            throw new BusinessException(CommonErrorCode.E_100113);
        }

        //手机号合法性校验
        if (!PhoneUtil.isMatches(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100109);
        }
        //用户名非空校验
        if (StringUtil.isEmpty(merchantDTO.getUsername())) {
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        //用户名唯一性校验
        Integer count = merchantMapper.selectCount(
                new LambdaQueryWrapper<Merchant>().eq(Merchant::getUsername, merchantDTO.getUsername()));
        if (count > 0) {
            throw new BusinessException(CommonErrorCode.E_100114);
        }

        //2.调用SaaS接口 添加 租户并绑定和门店 员工 商户之间的关系
        /**
         1、手机号
         2、账号
         3、密码
         4、租户类型：huimin-merchant
         5、默认套餐：huimin-merchant
         6、租户名称，同账号名
         */
        //创建 租户并初始化管理员
        CreateTenantRequestDTO createTenantRequestDTO = new CreateTenantRequestDTO();
        createTenantRequestDTO.setMobile(merchantDTO.getMobile());//手机号
        createTenantRequestDTO.setUsername(merchantDTO.getUsername());//账号
        createTenantRequestDTO.setPassword(merchantDTO.getPassword());//密码
        createTenantRequestDTO.setName(merchantDTO.getUsername());//租户名称
        createTenantRequestDTO.setBundleCode("huimin-merchant");// 套餐类型
        createTenantRequestDTO.setTenantTypeCode("huimin-merchant");//租户类型  签约商户
        //新增租户和账户
        TenantDTO tenantDTO = tenantService.createTenantAndAccount(createTenantRequestDTO);

        // 商户和租户一一对应
        Integer count1 = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>()
                .eq(Merchant::getTenantId, tenantDTO.getId()));
        if (count1>0){
            throw new BusinessException(CommonErrorCode.E_200017);
        }
        //创建商户
        Merchant merchant = MerchantCovert.INSTANCE.dto2entity(merchantDTO);
        //设置审核状态:0‐未申请,1‐已申请待审核,2‐审核通过,3‐审核拒绝
        merchant.setAuditStatus("0");
        merchant.setTenantId(tenantDTO.getId());//设置租户id


        /*Merchant merchant = new Merchant();
        //设置审核状态:0‐未申请,1‐已申请待审核,2‐审核通过,3‐审核拒绝
        merchant.setAuditStatus("0");
        //设置手机号 用户名
        merchant.setMobile(merchantDTO.getMobile());
        merchant.setUsername(merchantDTO.getUsername());*/
        //增加商户
        merchantMapper.insert(merchant);
        //获取新增的主键
        merchantDTO.setId(merchant.getId());

        //商户下新增门店
        StoreDTO storeDTO = new StoreDTO();
        storeDTO.setStoreName("谢同学的店");
        storeDTO.setMerchantId(merchant.getId());
        storeDTO.setStoreNumber(11111L);
        storeDTO.setStoreStatus(true); //设置默认参数
        storeDTO.setStoreAddress("银河系");
        //调用方法
        StoreDTO store = createStore(storeDTO);

        //添加后获取商店id
        Long storeId = store.getId();


        //4、新增员工-默认的管理员
        StaffDTO staffDTO = new StaffDTO();
        staffDTO.setMerchantId(merchant.getId());
        staffDTO.setUsername(merchantDTO.getUsername());
        staffDTO.setMobile(merchantDTO.getMobile());
        staffDTO.setStoreId(storeId); //商店id
        staffDTO.setStaffStatus(true); //状态

        staffDTO.setFullName("");//以后在saas中维护
        staffDTO.setPosition("");
        staffDTO.setLastLoginTime(LocalDateTime.now());//上次登陆时间
        //调用放法 添加会员
        StaffDTO staff = createStaff(staffDTO);
        //5、设置管理员-绑定关系
        bindStaffToStore(storeId,staff.getId()); //商店id  会员id

        return merchantDTO;
    }

    /**
     * 资质申请接口
     *
     * @param merchantId  商户id
     * @param merchantDTO 资质申请的信息
     * @throws BusinessException
     */
    @Override
    public void applyMerchant(Long merchantId, MerchantDTO merchantDTO) throws BusinessException {
        //校验商户信息
        if (merchantId == null || merchantDTO == null) {
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        //校验商户id 查询商户表 如果能查询到 表示这个商户可以申请资质
        Merchant merchant = merchantMapper.selectById(merchantId);
        if (merchant == null) {
            throw new BusinessException(CommonErrorCode.E_200002);
        }

        //dto转entity
        Merchant entity = MerchantCovert.INSTANCE.dto2entity(merchantDTO);
        //将必要的参数设置到entity
        entity.setId(merchantId);
        entity.setMobile(merchant.getMobile());//因为资质申请的时候手机号不让改，还使用数据库中原来的手机号
        entity.setAuditStatus("1");//审核状态1-已申请待审核
        entity.setUsername(merchant.getUsername());
        entity.setTenantId(merchant.getTenantId());

        //调用mapper更新商户表
        merchantMapper.updateById(entity);
    }

    /**
     * 商户下新增门店
     * @param storeDTO 商店信息
     */
    @Override
    public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {
        Store store = StoreConvert.INSTANCE.dto2entity(storeDTO);
        //添加
        storeMapper.insert(store);
        return StoreConvert.INSTANCE.entity2dto(store);


    }

    /**
     * 商户新增员工
     *
     * @param staffDTO
     */
    @Override
    public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {
        //校验手机号是否存在
        if (StringUtil.isBlank(staffDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        //根据手机号和商户id校验员工唯一性
        if(isExistStaffByMobile(staffDTO.getMobile(),staffDTO.getMerchantId())){
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        //校验用户名是否为空
        if (StringUtil.isBlank(staffDTO.getUsername())) {
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        //根据商户id和账号校验唯一性
        if(isExistStaffByUserName(staffDTO.getUsername(), staffDTO.getMerchantId())){
            throw new BusinessException(CommonErrorCode.E_100114);
        }
        Staff staff = StaffConvert.INSTANCE.dto2entity(staffDTO);
        staffMapper.insert(staff);
        return StaffConvert.INSTANCE.entity2dto(staff);
    }

    /**
     * 为门店设置管理员
     *
     * @param storeId 商店id
     * @param staffId 员工id
     * @throws BusinessException
     */
    @Override
    public void bindStaffToStore(Long storeId, Long staffId) throws BusinessException {
        StoreStaff storeStaff = new StoreStaff();
        storeStaff.setStoreId(storeId);
        storeStaff.setStaffId(staffId);
        storeStaffMapper.insert(storeStaff);

    }

    /**
     * 根据租户id查询商户的信息
     *
     * @param tenantId
     * @return
     */
    @Override
    public MerchantDTO queryMerchantByTenantId(Long tenantId) {
        Merchant merchant = merchantMapper.selectOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantId));
        return MerchantCovert.INSTANCE.entity2dto(merchant);
    }

    /**
     * 根据账号判断员工是否已在指定商户存在
     * @param userName
     * @param merchantId
     * @return
     */
    private boolean isExistStaffByUserName(String userName, Long merchantId) {
        LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<Staff>();
        lambdaQueryWrapper.eq(Staff::getUsername, userName).eq(Staff::getMerchantId,merchantId);
        int i = staffMapper.selectCount(lambdaQueryWrapper);
        return i > 0;
    }

    /**
     * 根据手机号判断员工是否已在指定商户存在
     * @param mobile 手机号
     * @return
     */
    private boolean isExistStaffByMobile(String mobile, Long merchantId) {
        LambdaQueryWrapper<Staff> wrapper = new LambdaQueryWrapper<Staff>()
                .eq(Staff::getMobile, mobile)
                .eq(Staff::getMerchantId, merchantId);
        return staffMapper.selectCount(wrapper) > 0;
    }
}